package homelesspartners.client;

import homelesspartners.client.model.City;
import homelesspartners.client.model.Gift;
import homelesspartners.client.model.Shelter;
import homelesspartners.client.model.Story;
import homelesspartners.client.model.ThankYou;
import homelesspartners.client.model.ThankYouPages;
import homelesspartners.client.model.User;
import homelesspartners.client.widgets.HomeTabWidget;
import homelesspartners.client.widgets.ProcessingWidget;
import homelesspartners.client.widgets.ShoppingListWidget;
import homelesspartners.client.widgets.ThankYouNotesWidget;
import homelesspartners.client.widgets.ThankyouTabWidget;
import homelesspartners.client.widgets.VolunteerTabWidget;

import java.util.ArrayList;

import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.rpc.ServiceDefTarget;

public class ServerFacade {

	private static ProcessingWidget processingWidget = new ProcessingWidget();

	public static void loadCities() {

		ServiceAsync service = getService();

		AsyncCallback callback = new AsyncCallback() {

			public void onSuccess(Object result) {
				stop();
				Controller.updateCitiesList((ArrayList) result);
			}

			public void onFailure(Throwable ex) {
				stop();
				Controller.updateCitiesList(null);
			}
		};

		service.getCities(callback);

	}

	private static ServiceAsync getService() {
		start();
		ServiceAsync service = (ServiceAsync) GWT.create(Service.class);
		ServiceDefTarget endPoint = (ServiceDefTarget) service;
		endPoint.setServiceEntryPoint(GWT.getHostPageBaseURL() + "/hpService");
		return service;
	}

	public static void loadShelters(final City aCity) {
		ServiceAsync service = getService();

		AsyncCallback callback = new AsyncCallback() {

			public void onSuccess(Object result) {
				Controller.updateSheltersList(aCity, (ArrayList) result);
				stop();
			}

			public void onFailure(Throwable ex) {
				Controller.updateSheltersList(aCity, (ArrayList) null);
				stop();
			}
		};

		service.getShelters(aCity.getId(), callback);
	}

	private static void start() {
		processingWidget.center();
		processingWidget.show();
	}

	protected static void stop() {
		processingWidget.hide();
	}

	public static void loadStories(final int shelterId, String idQuery, String nameQuery) {
		ServiceAsync service = getService();

		AsyncCallback callback = new AsyncCallback() {

			public void onSuccess(Object result) {
				stop();
				VolunteerTabWidget.getInstance().completedLoadStories(shelterId, result);
			}

			public void onFailure(Throwable ex) {
				stop();
				VolunteerTabWidget.getInstance().failedLoadStories(ex);
			}
		};

		service.getStories(shelterId, idQuery, nameQuery, callback);
	}

	public static void pledgeGift(final Gift gift) {
		ServiceAsync service = getService();

		AsyncCallback callback = new AsyncCallback() {

			public void onSuccess(Object result) {
				stop();
				boolean pledged = ((Boolean) result).booleanValue();
				if (pledged) {
					gift.setDonor(User.getInstance().getEmailAddress());
					ShoppingListWidget.getInstance().addGift(gift);
				} else {
					Window
							.alert("We're sorry, the gift was just pledged by another person.  Please continue browsing the site and see if there's another gift you'd like to give instead.  Thank you for your support!");
				}
			}

			public void onFailure(Throwable ex) {
				stop();
				Window.alert("Could not record the pledge.");
				if (ex != null) {
					Window.alert(ex.getMessage());
				}
			}
		};

		service.pledgeGift(gift.getId(), callback);
	}

	public static void login(String userId, String password) {
		ServiceAsync service = getService();

		AsyncCallback callback = new AsyncCallback() {

			public void onSuccess(Object result) {
				stop();
				User user = (User) result;
				if (user != null) {
					Controller.updateLogin(user);
				} else {
					Controller.unableToLogin();
				}
			}

			public void onFailure(Throwable ex) {
				stop();
				Controller.unableToLogin();
			}
		};

		service.login(userId, password, callback);
	}

	public static void createNewUser(String userId, String password) {
		ServiceAsync service = getService();

		AsyncCallback callback = new AsyncCallback() {

			public void onSuccess(Object result) {
				stop();
				User user = (User) result;
				if (user != null) {
					Controller.updateLogin(user);
				} else {
					Controller.unableToCreateNewUser();
				}
			}

			public void onFailure(Throwable ex) {
				stop();
				Controller.unableToCreateNewUser();
			}
		};

		service.createNewUser(userId, password, callback);
	}

	public static void loadShoppingList() {
		ServiceAsync service = getService();

		AsyncCallback callback = new AsyncCallback() {

			public void onSuccess(Object result) {
				stop();
				ArrayList gifts = (ArrayList) result;
				if (gifts != null) {
					ShoppingListWidget.getInstance().addGifts(gifts);
				} else {
					Controller.unableToLoadShoppingList();
				}
			}

			public void onFailure(Throwable ex) {
				stop();
				Controller.unableToLoadShoppingList();
			}
		};

		service.getShoppingList(callback);
	}

	public static void addInterview(final Story story) {
		ServiceAsync service = getService();

		AsyncCallback callback = new AsyncCallback() {

			public void onSuccess(Object result) {
				stop();
				VolunteerTabWidget.getInstance().completedAddInterview(result);
			}

			public void onFailure(Throwable ex) {
				stop();
				VolunteerTabWidget.getInstance().failedAddInterview(ex);
			}
		};

		service.addInterview(story, callback);

	}
	
	public static void addInterviewCheckFirst(final Story story) {
		ServiceAsync service = getService();

		AsyncCallback callback = new AsyncCallback() {

			public void onSuccess(Object result) {
				stop();
				VolunteerTabWidget.getInstance().completedAddInterviewCheckFirst(result);
			}

			public void onFailure(Throwable ex) {
				stop();
				VolunteerTabWidget.getInstance().failedAddInterview(ex);
			}
		};

		service.addInterviewCheckFirst(story, callback);

	}

	public static void addShelter(final Shelter shelter) {
		ServiceAsync service = getService();

		AsyncCallback callback = new AsyncCallback() {

			public void onSuccess(Object result) {
				stop();
				VolunteerTabWidget.getInstance().completedAddShelter(result);
			}

			public void onFailure(Throwable ex) {
				stop();
				VolunteerTabWidget.getInstance().failedAddShelter(ex);
			}
		};

		service.addShelter(shelter, callback);

	}

	public static void removePledge(final Gift gift) {
		ServiceAsync service = getService();

		AsyncCallback callback = new AsyncCallback() {

			public void onSuccess(Object result) {
				stop();
				boolean unpledged = ((Boolean) result).booleanValue();
				if (unpledged) {
					gift.setDonor(null);
					Controller.removeFromShoppingList(gift);
				} else {
					Window.alert("Could not remove the gift");
				}
			}

			public void onFailure(Throwable ex) {
				stop();
				Window.alert("Could not remove the gift");
				if (ex != null) {
					Window.alert(ex.getMessage());
				}
			}
		};

		service.unpledgeGift(gift.getId(), callback);
	}

	public static void deleteInterview(int storyId) {
		ServiceAsync service = getService();

		AsyncCallback callback = new AsyncCallback() {

			public void onSuccess(Object result) {
				stop();
				VolunteerTabWidget.getInstance().completedDeleteInterview(result);
			}

			public void onFailure(Throwable ex) {
				stop();
				VolunteerTabWidget.getInstance().failedDeletedInterview(ex);
			}
		};

		service.deleteStory(storyId, callback);
	}

	public static void updateInterview(Story story) {
		ServiceAsync service = getService();

		AsyncCallback callback = new AsyncCallback() {

			public void onSuccess(Object result) {
				stop();
				VolunteerTabWidget.getInstance().completedUpdateInterview(result);
			}

			public void onFailure(Throwable ex) {
				stop();
				VolunteerTabWidget.getInstance().failedUpdateInterview(ex);
			}
		};

		service.updateStory(story, callback);
	}

	public static void updateShelter(Shelter shelter) {
		ServiceAsync service = getService();

		AsyncCallback callback = new AsyncCallback() {

			public void onSuccess(Object result) {
				stop();
				VolunteerTabWidget.getInstance().completedUpdateShelter(result);
			}

			public void onFailure(Throwable ex) {
				stop();
				VolunteerTabWidget.getInstance().failedUpdateShelter(ex);
			}
		};

		service.updateShelter(shelter, callback);
	}

	public static void deleteShelter(int shelterId) {
		ServiceAsync service = getService();

		AsyncCallback callback = new AsyncCallback() {

			public void onSuccess(Object result) {
				stop();
				VolunteerTabWidget.getInstance().completedDeleteShelter(result);
			}

			public void onFailure(Throwable ex) {
				stop();
				VolunteerTabWidget.getInstance().failedDeletedShelter(ex);
			}
		};

		service.deleteShelter(shelterId, callback);
	}

	public static void loadPageOfStories(final Shelter shelter, int offset) {
		shelter.setLoading(true);
		ServiceAsync service = getService();

		AsyncCallback callback = new AsyncCallback() {

			public void onSuccess(Object result) {
				stop();
				shelter.setLoading(false);
				Controller.completeLoadPageOfStories(shelter, result);
			}

			public void onFailure(Throwable ex) {
				stop();
				shelter.setLoading(false);
				Controller.failedLoadPageOfStories(ex);
			}
		};

		service.getPageOfStories(shelter.getId(), offset, callback);
	}

	public static void sendPassword(String email) {
		ServiceAsync service = getService();

		AsyncCallback callback = new AsyncCallback() {

			public void onSuccess(Object result) {
				stop();
			}

			public void onFailure(Throwable ex) {
				stop();
			}
		};

		service.sendPassword(email, callback);

	}

	public static void createNewVolunteer(User volunteer) {
		ServiceAsync service = getService();

		AsyncCallback callback = new AsyncCallback() {

			public void onSuccess(Object result) {
				stop();
				VolunteerTabWidget.getInstance().completedCreateNewVolunteer(result);
			}

			public void onFailure(Throwable ex) {
				stop();
				VolunteerTabWidget.getInstance().failedCreateNewVolunteer(ex);
			}
		};

		service.createNewVolunteer(volunteer, callback);
	}

	public static void updateVolunteer(User volunteer) {
		ServiceAsync service = getService();

		AsyncCallback callback = new AsyncCallback() {

			public void onSuccess(Object result) {
				stop();
				VolunteerTabWidget.getInstance().completedUpdateVolunteer(result);
			}

			public void onFailure(Throwable ex) {
				stop();
				VolunteerTabWidget.getInstance().failedUpdateVolunteer(ex);
			}
		};

		service.updateVolunteer(volunteer, callback);
	}

	public static void updatePassword(String password) {
		ServiceAsync service = getService();

		AsyncCallback callback = new AsyncCallback() {

			public void onSuccess(Object result) {
				stop();
				VolunteerTabWidget.getInstance().completedUpdatePassword(result);
			}

			public void onFailure(Throwable ex) {
				stop();
				VolunteerTabWidget.getInstance().failedUpdatePassword(ex);
			}
		};

		service.updatePassword(password, callback);
	}

	public static void loadPageOfThankYous(int pageNumber) {
		ServiceAsync service = getService();

		AsyncCallback callback = new AsyncCallback() {

			public void onSuccess(Object result) {
				stop();
				ThankYouPages.getInstance().addPage((ArrayList) result);
				ThankYouNotesWidget.getInstance().refresh();
			}

			public void onFailure(Throwable ex) {
				stop();
				Window.alert("Could not load the thank you notes");
			}
		};

		service.getPageOfThankYous(pageNumber, callback);
	}

	public static void addThankYou(ThankYou thankyou) {
		ServiceAsync service = getService();

		AsyncCallback callback = new AsyncCallback() {

			public void onSuccess(Object result) {
				stop();
				Boolean theResult = (Boolean) result;
				if(theResult.booleanValue()){
					Window.alert("The note was successfully added!");
					VolunteerTabWidget.getInstance().clearThankYouForm();
				} else {
					onFailure(null);
				}
			}

			public void onFailure(Throwable ex) {
				stop();
				Window.alert("Could not add the note");
				if (ex != null) {
					Window.alert(ex.getMessage());
				}
			}
		};

		service.addThankYou(thankyou, callback);
	}

	public static void updateThankYou(ThankYou thankyou) {
		ServiceAsync service = getService();

		AsyncCallback callback = new AsyncCallback() {

			public void onSuccess(Object result) {
				stop();
				Boolean theResult = (Boolean) result;
				if(theResult.booleanValue()){
					Window.alert("The note was successfully updated!");
				} else {
					onFailure(null);
				}
			}

			public void onFailure(Throwable ex) {
				stop();
				Window.alert("Could not update the note");
				if (ex != null) {
					Window.alert(ex.getMessage());
				}
			}
		};

		service.updateThankYou(thankyou, callback);
	}

	public static void deleteThankYou(int id) {
		ServiceAsync service = getService();

		AsyncCallback callback = new AsyncCallback() {

			public void onSuccess(Object result) {
				stop();
				VolunteerTabWidget.getInstance().completedDeleteThankYou(result);
			}

			public void onFailure(Throwable ex) {
				stop();
				VolunteerTabWidget.getInstance().failedDeleteThankYou(ex);
			}
		};

		service.deleteThankYou(id, callback);
	}

	public static void getThankYous(String headerQuery) {
		ServiceAsync service = getService();

		AsyncCallback callback = new AsyncCallback() {

			public void onSuccess(Object result) {
				stop();
				VolunteerTabWidget.getInstance().completedGetThankYous(result);
			}

			public void onFailure(Throwable ex) {
				stop();
				VolunteerTabWidget.getInstance().failedGetThankYous(ex);
			}
		};

		service.getThankYous(headerQuery, callback);
	
	}

	public static void getThankYouStats() {
		ServiceAsync service = getService();

		AsyncCallback callback = new AsyncCallback() {

			public void onSuccess(Object result) {
				stop();
				ArrayList theResult = (ArrayList) result;
				if(theResult.size() >= 2){
					ThankyouTabWidget.getInstance().initThankYouMessage(theResult);
					HomeTabWidget.getInstance().updateStats(theResult);
				} else {
					onFailure(null);
				}
			}

			public void onFailure(Throwable ex) {
				stop();
			}
		};

		service.getThankYouStats(callback);
	}

}
